#include "EtgRecEscrituraDirecta.h"


EtgRecEscrituraDirecta::EtgRecEscrituraDirecta(TipoMemoria tipoMemoria,TipoIndice tipoIndice,EstrategiaIndice *indice,TipoAlmacenamiento tipoAlmacenamiento,TipoEstrategia tipoEstrategia,Almacenamiento **persistencia,void* ptr,PrimaryKey *PK){
     //this->indice = indice;
     if (tipoIndice==HASH)
     	this->indice=(EstrategiaIndice*) new IndiceHashExtensible(PK);
     this->tipoIndice = tipoIndice;
     this->PK = PK;
     this->persistencia = persistencia;
     vector<Dato*> vec;    
     vec.clear();
     switch(tipoEstrategia){          
          case REGISTROS:
               this->estrategiaAlm = new EstrategiaRegistros(persistencia,AMBOS);
               this->tipoSerializacion = BINARIO;
               break;
          case BLOQUES:
               this->estrategiaAlm = new EstrategiaBloques(persistencia,AMBOS);
               this->tipoSerializacion = BINARIO;
               break;
          case TEXT:
               this->estrategiaAlm = new EstrategiaTexto(persistencia,AMBOS);
               this->tipoSerializacion = TEXTO;               
     }
     this->estrategiaAlm->crear(tipoMemoria,vec,ptr);                                                           
}

void EtgRecEscrituraDirecta::insertar(Dato *datoNvo){
     if(this->tipoIndice==ARBOL)
         this->insertarArbol(datoNvo);
     else if(this->tipoIndice==HASH)
         this->insertarHashing(datoNvo);     
}

void EtgRecEscrituraDirecta::insertarArbol(Dato *dato){
     int nro;
     try{
          this->estrategiaAlm->insertar(dato,&nro);
     }
     catch(exception *e){
          throw e;                
     }
     void* datoSerializado=NULL;
     dato->serialize(&datoSerializado,this->tipoSerializacion);
     try{
          this->indice->Cargar((char*)datoSerializado,(unsigned int) nro);
     }
     catch(exception *e){
          this->estrategiaAlm->eliminar(dato,nro);               
          throw e;
     }     
}

void EtgRecEscrituraDirecta::insertarHashing(Dato *dato){
     void* datoSerializado=NULL;
     dato->serialize(&datoSerializado,this->tipoSerializacion);
     this->indice->Cargar((char*)datoSerializado,dato->getTamanio(BINARIO));
     vector<HashChange>* vecAux = ((IndiceHashExtensible*) this->indice)->getModificaciones();   
     this->ejecutarCambios(vecAux);
     vecAux->clear();
     free(datoSerializado);
}

void EtgRecEscrituraDirecta::ejecutarCambios(vector<HashChange> *vecAux){
     Dato *datoAux;
     vector<HashChange>:: iterator it;
     for (it=vecAux->begin(); it != vecAux->end(); it++){
         Compuesto *compuestoAux;
         compuestoAux = this->persistencia[0]->getCompuesto();
        
         ((EstrategiaBloques*) this->estrategiaAlm)->buscar(&datoAux,it->getBloqueAnterior(),it->getClave(),this->tipoSerializacion,this->PK);
         this->estrategiaAlm->eliminar(datoAux,it->getBloqueAnterior());
         int bloqueActual = it->getBloqueActual();
         this->estrategiaAlm->insertar(datoAux,&bloqueActual);
     }       
}

void EtgRecEscrituraDirecta::modificar(Dato *datoNvo){
     if(this->tipoIndice==ARBOL)
         this->modificarArbol(datoNvo);
     else if(this->tipoIndice==HASH)
         this->modificarHashing(datoNvo);         
}

void EtgRecEscrituraDirecta::modificarArbol(Dato *dato){ 

	void* datoSerializadoNuevo=NULL;
    dato->serialize(&datoSerializadoNuevo,this->tipoSerializacion);
    int aux;
    int pos;
    char* chrClave = this->PK->GetKey((char*)datoSerializadoNuevo,aux);
    string *strClave = new string(chrClave);
    free(chrClave);
    vector<unsigned int> vec = this->indice->Buscar(*strClave);
    vector<unsigned int>:: iterator it;
    it=vec.begin();
    this->estrategiaAlm->eliminar(dato,*it);
    this->estrategiaAlm->insertar(dato,&pos);
    this->indice->Cargar((char*)datoSerializadoNuevo, pos);	
	
	
	    
}

void EtgRecEscrituraDirecta::modificarHashing(Dato *dato){
     void* datoSerializadoNuevo=NULL;
     dato->serialize(&datoSerializadoNuevo,this->tipoSerializacion);
     void* datoSerializadoViejo=NULL;
     int aux;
     char* chrClave = this->PK->GetKey((char*)datoSerializadoNuevo,aux);
     string *strClave = new string(chrClave);
     free(chrClave);
     vector<unsigned int> vec = this->indice->Buscar(*strClave);
     vector<unsigned int>:: iterator it;
     it=vec.begin();
     Dato *datoAux=NULL;
     dato->clone(datoAux);
     this->estrategiaAlm->leer(datoAux,*it);
     datoAux->serialize(&datoSerializadoViejo,this->tipoSerializacion);
     
     this->indice->Modificar((char*)datoSerializadoViejo,(char*)datoSerializadoNuevo,dato->getTamanio(BINARIO),datoAux->getTamanio(BINARIO));
     delete(datoAux);
     free(datoSerializadoViejo);
     free(datoSerializadoNuevo);
     vector<HashChange>* vecAux = ((IndiceHashExtensible*) this->indice)->getModificaciones();   
     this->ejecutarCambios(vecAux);
     vecAux->clear();
     delete(strClave);
}
     

void EtgRecEscrituraDirecta::eliminar(Dato *datoNvo){
     if(this->tipoIndice==ARBOL)
         this->eliminarArbol(datoNvo);
     else if(this->tipoIndice==HASH)
         this->eliminarHashing(datoNvo);              
}

void EtgRecEscrituraDirecta::eliminarArbol(Dato *dato){
	void* datoSerializadoNuevo=NULL;
    dato->serialize(&datoSerializadoNuevo,this->tipoSerializacion);
    int aux;
    char* chrClave = this->PK->GetKey((char*)datoSerializadoNuevo,aux);
    string *strClave = new string(chrClave);
    free(chrClave);
    vector<unsigned int> vec = this->indice->Buscar(*strClave);
    vector<unsigned int>:: iterator it;
    it=vec.begin();
    this->estrategiaAlm->eliminar(dato,*it);
    this->indice->Eliminar((char*)datoSerializadoNuevo);         
}

void EtgRecEscrituraDirecta::eliminarHashing(Dato *dato){
     void* datoSerializado=NULL;
     dato->serialize(&datoSerializado,this->tipoSerializacion);
     this->indice->Eliminar((char*)datoSerializado);
     vector<HashChange>* vecAux = ((IndiceHashExtensible*) this->indice)->getModificaciones();   
     this->ejecutarCambios(vecAux);
     vecAux->clear();
     free(datoSerializado);    
}

void EtgRecEscrituraDirecta::leer(Dato *datoAux){
	void* datoSerializadoNuevo=NULL;
    datoAux->serialize(&datoSerializadoNuevo,this->tipoSerializacion);
    int aux;
    char* chrClave = this->PK->GetKey((char*)datoSerializadoNuevo,aux);
    string *strClave = new string(chrClave);
    free(chrClave);
    vector<unsigned int> vec = this->indice->Buscar(*strClave);
    vector<unsigned int>:: iterator it;
    it=vec.begin();
    this->estrategiaAlm->leer(datoAux,*it);         
}




/*void EtgRecEscrituraDirecta::listar(Dato *dini, Dato *dfin){//TODO}*/

